package com.progenies.ecg.asm31.model.codeparts;

import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import com.progenies.ecg.asm31.util.BytecodeInstructionsUtils;
import com.progenies.ecg.asm31.util.VariableRegister;
import com.progenies.ecg.model.AbstractCodeObject;
import com.progenies.ecg.model.codeparts.CodeBlock;
import com.progenies.ecg.model.codeparts.DoWhileLoopCodePart;
import com.progenies.ecg.model.conditions.ICondition;

public class DoWhileLoopCodePartASM31 extends DoWhileLoopCodePart implements IConfigurableCodePart, ILoopASM31 {

	protected MethodVisitor visitor;
	protected AbstractCodeObject parent;
	protected VariableRegister varRegister;
	
	
	protected Label startLabel;
	protected Label postIterateLabel;
	protected Label endLabel;
	
	public DoWhileLoopCodePartASM31(ICondition condition, CodeBlock bodyBlock)
	{
		this.condition=condition;
		this.bodyBlock=bodyBlock;
	}
	
	@Override
	public void generateBytecode()
	{
		//Labels: start, postIterate and end
		startLabel=BytecodeInstructionsUtils.createAndVisitLabel(visitor);
		postIterateLabel=new Label();
		endLabel=new Label();
				
		//generate body block
		if(this.bodyBlock!=null)
			this.bodyBlock.generateBytecode();
		
		//postIterateLoop
		visitor.visitLabel(postIterateLabel);
		
		//evaluate condition (do-while loop, evaluate AFTER executing)
		//If no condition, just do nothing...
		if(condition!=null)
		{
			BytecodeInstructionsUtils.evaluateCondition(visitor, condition, endLabel, varRegister, parent);
		}

		
		//if code reach here, jump to start label
		visitor.visitJumpInsn(Opcodes.GOTO, startLabel);
				
		//visit end label, code jumps here on fail condition evaluation or "break" instruction
		visitor.visitLabel(endLabel);
	}
	
	@Override
	public boolean isReturnCodePart() {
		return false;
	}

	@Override
	public Label getStartLabel() {
		return startLabel;
	}

	@Override
	public Label getPostIterationLabel() {
		return postIterateLabel;
	}

	@Override
	public Label getEndLabel() {
		return endLabel;
	}

	@Override
	public void configure(MethodVisitor visitor, AbstractCodeObject parent,	VariableRegister varRegister)
	{
		this.visitor=visitor;
		this.parent=parent;
		this.varRegister=varRegister;
		
		if(this.bodyBlock!=null && this.bodyBlock instanceof IConfigurableCodePart)
			((IConfigurableCodePart)this.bodyBlock).configure(visitor, this, varRegister);
	}


}
